<template>
  <div class="chart-wrapper">
    <div class="chart-title">
      {{ title }}
    </div>
    <div :id="chartId" class="chart" :style="getChartStyle"></div>
  </div>
</template>

<script>
import * as echarts from 'echarts';

export default {
  name: 'MixedChart',
  props: {
    /**
     * 图表标题
     * @example '销售趋势分析'
     */
    title: {
      type: String,
      default: '',
    },

    /**
     * 图表类型配置
     * @description 配置两个系列的图表类型
     * @example { primary: 'bar', secondary: 'line' }
     */
    seriesTypes: {
      type: Object,
      default: () => ({
        primary: 'bar',
        secondary: 'line',
      }),
      validator: value => {
        const validTypes = ['bar', 'line'];
        return validTypes.includes(value.primary) && validTypes.includes(value.secondary);
      },
    },

    /**
     * 是否共用Y轴
     * @description 当两个系列类型相同时，是否使用同一个Y轴
     * @example true - 共用Y轴，false - 使用独立Y轴
     */
    shareYAxis: {
      type: Boolean,
      default: true,
    },

    /**
     * 柱状图数据
     * @description 第一个系列的数据配置
     * @example { categories: ['一月', '二月'], values: [100, 200] }
     */
    primaryData: {
      type: Object,
      required: true,
    },

    /**
     * 折线图数据
     * @description 第二个系列的数据配置
     * @example { categories: ['一月', '二月'], values: [50, 80] }
     */
    secondaryData: {
      type: Object,
      required: true,
    },

    /**
     * 图表配置项
     * @description 图表的详细配置，包括坐标轴、图例等
     */
    chartConfig: {
      type: Object,
      default: () => ({
        height: 400,
        // 背景色配置
        backgroundColor: '#fff',
        // 标题配置
        title: {
          show: true,
          text: '销售额与趋势值对比分析',
          textStyle: {
            fontFamily: 'Calibri Light',
            fontSize: 16,
          },
        },
        // 提示框配置
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'cross',
            crossStyle: {
              color: '#999',
            },
          },
        },
        // 图例配置
        legend: {
          data: ['销售额', '趋势值'],
          bottom: 10,
        },
        // 网格配置
        grid: {
          left: '3%',
          right: '5%',
          bottom: '15%',
          containLabel: true,
        },
        // 坐标轴配置
        axis: {
          // 分类轴配置
          category: {
            axisLabel: {
              color: '#494949',
              fontFamily: 'Arial',
              fontSize: 10,
            },
            name: '月份',
            nameLocation: 'middle',
            nameGap: 30,
          },
          // 主值轴配置（销售额）
          primary: {
            name: '销售额',
            min: 0,
            axisLabel: {
              formatter: '{value}',
              color: '#5470c6',
              fontSize: 10,
            },
            nameTextStyle: {
              color: '#5470c6',
              fontSize: 12,
            },
          },
          // 次值轴配置（趋势值）
          secondary: {
            name: '趋势值',
            min: 0,
            axisLabel: {
              formatter: '{value}',
              color: '#91cc75',
            },
            nameTextStyle: {
              color: '#91cc75',
              fontSize: 12,
            },
          },
        },
        // 系列配置
        series: {
          // 主系列配置
          primary: {
            name: '销售额',
            itemStyle: {
              color: '#5470c6',
            },
          },
          // 次系列配置
          secondary: {
            name: '趋势值',
            itemStyle: {
              color: '#91cc75',
            },
          },
          // 柱状图通用配置
          bar: {
            barWidth: '40%',
            itemStyle: {
              color: '#5470c6',
            },
          },
          // 折线图通用配置
          line: {
            itemStyle: {
              color: '#91cc75',
            },
            lineStyle: {
              width: 3,
            },
            symbol: 'circle',
            symbolSize: 8,
            smooth: true,
          },
        },
      }),
    },

    /**
     * PPT导出配置
     * @description PPT导出时的样式和布局配置
     */
    pptOptions: {
      type: Object,
      default: () => ({
        // 图表位置和大小
        position: {
          x: 0.5,
          y: 1.0,
          w: 9,
          h: '70%',
        },
        // 标题配置
        title: {
          x: 0.5,
          y: 0.5,
          fontSize: 24,
          color: '363636',
          bold: true,
        },
        // 图表配置
        chart: {
          // 图表标题
          showTitle: true,
          title: '销售额与趋势值对比分析',
          titleFontFace: 'Calibri Light',

          // 图例配置
          showLegend: true,
          legendPos: 'b',
          // 图表区域
          chartArea: {
            // fill: { color: 'F1F1F1' },
          },

          // 分类轴配置
          catAxisLabelColor: '494949',
          catAxisLabelFontFace: 'Arial',
          catAxisLabelFontSize: 10,
          catAxisOrientation: 'minMax',
          catAxes: [{ catAxisTitle: '月份' }, { catAxisHidden: true }],
          showValue: true,
          dataLabelFormatCode: ['[黑色],##0.00', '[黑色],##0.00'],
          dataLabelFontSize: 7,
          // 值轴配置
          values: [
            {
              // 主值轴（销售额）
              showValAxisTitle: true,
              valAxisTitle: '销售额',
              valAxisTitleColor: '5470c6',
              valAxisLabelColor: '5470c6',
              valAxisTitleFontSize: 12,
              valGridLine: { style: 'solid' }, // 添加主轴网格线配置
            },
            {
              // 次值轴（趋势值）
              showValAxisTitle: true,
              valAxisTitle: '趋势值',
              valAxisTitleColor: '91cc75',
              valAxisLabelColor: '91cc75',
              valGridLine: { style: 'none' },
              valAxisTitleFontSize: 12,
            },
          ],

          // 系列配置
          series: {
            bar: {
              color: '5470c6',
              barDir: 'col',
              barGrouping: 'clustered',
            },
            line: {
              color: '91cc75',
              lineSize: 3,
              lineDataSymbol: 'circle',
              lineDataSymbolSize: 8,
              lineSmooth: true,
            },
          },
        },
      }),
    },
  },

  data() {
    return {
      // echarts实例
      chart: null,
      chartId: Math.random().toString(36).substring(2, 15),
    };
  },

  methods: {
    /**
     * 初始化图表
     * @description 创建echarts实例并首次渲染
     */
    initChart() {
      const chartDom = document.getElementById(this.chartId);
      if (!chartDom) return;

      this.chart = echarts.init(chartDom);
      this.updateChart();
    },

    /**
     * 更新图表数据和配置
     * @description 根据props更新图表的数据和配置项
     */
    updateChart() {
      if (!this.chart) return;
      // 判断是否需要使用双Y轴
      const useDoubleYAxis = this.seriesTypes.primary !== this.seriesTypes.secondary || (this.seriesTypes.primary === this.seriesTypes.secondary && !this.shareYAxis);
      const option = {
        backgroundColor: this.chartConfig.backgroundColor,
        title: this.chartConfig.title,
        tooltip: this.chartConfig.tooltip,
        legend: {
          ...this.chartConfig.legend,
          data: [this.chartConfig.series.primary.name, this.chartConfig.series.secondary.name],
        },
        grid: this.chartConfig.grid,
        xAxis: [
          {
            type: 'category',
            data: this.primaryData.categories,
            axisPointer: {
              type: 'shadow',
            },
            ...this.chartConfig.axis.category,
          },
        ],
        yAxis: [
          {
            type: 'value',
            ...this.chartConfig.axis.primary,
          },
          {
            type: 'value',
            ...this.chartConfig.axis.secondary,
            show: useDoubleYAxis,
          },
        ],
        series: [
          {
            type: this.seriesTypes.primary,
            data: this.primaryData.values,
            name: this.chartConfig.series.primary.name,
            label: this.chartConfig.series.label,
            ...(this.seriesTypes.primary === 'bar'
              ? {
                  ...this.chartConfig.series.bar,
                  itemStyle: this.chartConfig.series.primary.itemStyle,
                }
              : {
                  ...this.chartConfig.series.line,
                  itemStyle: this.chartConfig.series.primary.itemStyle,
                }),
          },
          {
            type: this.seriesTypes.secondary,
            yAxisIndex: useDoubleYAxis ? 1 : 0,
            data: this.secondaryData.values,
            name: this.chartConfig.series.secondary.name,
            label: this.chartConfig.series.label,
            ...(this.seriesTypes.secondary === 'bar'
              ? {
                  ...this.chartConfig.series.bar,
                  itemStyle: this.chartConfig.series.secondary.itemStyle,
                }
              : {
                  ...this.chartConfig.series.line,
                  itemStyle: this.chartConfig.series.secondary.itemStyle,
                }),
          },
        ],
      };

      this.chart.setOption(option);
    },

    /**
     * 调整图表大小
     * @description 在容器大小变化时自动调整图表大小
     */
    resizeChart() {
      this.chart && this.chart.resize();
    },

    /**
     * 导出为PPT
     * @description 将图表导出为PPT格式
     * @param {Object} pptx pptxgen实例
     * @param {Object} slide 当前幻灯片实例
     */
    exportToPPT(pptx, slide) {
      // 添加图表标题
      slide.addText(this.title, {
        x: this.pptOptions.title.x,
        y: this.pptOptions.title.y,
        fontSize: this.pptOptions.title.fontSize,
        color: this.pptOptions.title.color,
        bold: this.pptOptions.title.bold,
      });

      // 准备数据
      const chartData = [
        {
          name: this.chartConfig.series.primary.name,
          labels: this.primaryData.categories,
          values: this.primaryData.values,
        },
        {
          name: this.chartConfig.series.secondary.name,
          labels: this.secondaryData.categories,
          values: this.secondaryData.values,
        },
      ];

      // 判断是否为双柱状图
      const isDoubleBar = this.seriesTypes.primary === 'bar' && this.seriesTypes.secondary === 'bar';

      if (isDoubleBar) {
        // 3D柱状图配置
        const chartConfig = {
          x: this.pptOptions.position.x,
          y: this.pptOptions.position.y,
          w: this.pptOptions.position.w,
          h: this.pptOptions.position.h,
          // 柱状图样式
          chartColors: this.primaryData.values.map(value => (value >= 0 ? this.chartConfig.series.primary.itemStyle.color.replace('#', '') : 'ee6666')),
          barDir: 'col',
          bar3DShape: 'coneToMax',
          v3DRAngAx: true,
          showLegend: this.pptOptions.chart.showLegend,
          legendPos: 'b',
          // 系列轴配置
          serAxisLabelColor: this.chartConfig.series.primary.itemStyle.color.replace('#', ''),
          // 数据标签配置
          dataLabelPosition: 'ctr',
          showValue: true,
          titleColor: this.chartConfig.series.primary.itemStyle.color.replace('#', ''),
        };

        // 添加3D柱状图
        slide.addChart(pptx.charts.BAR3D, chartData, chartConfig);
      } else {
        let { position, chart } = this.pptOptions;
        // 组合图表配置
        const comboProps = {
          x: position.x,
          y: position.y,
          w: position.w,
          h: position.h,
          // 网格配置
          valGridLine: { style: 'none' },
          catGridLine: { style: 'none' },
          // 图例配置
          showLegend: chart.showLegend,
          legendPos: chart.legendPos,
          showValue: chart.showValue,
          catAxes: chart.catAxes,
          // 分类轴字体大小
          catAxisLabelFontSize: 8,
          // 柱状图间距
          barGapWidthPct: 100,
          // 数据标签字体大小
          dataLabelFontSize: chart.dataLabelFontSize,
          // 值轴配置
          valAxes: [
            {
              showValAxisTitle: chart.values[0].showValAxisTitle,
              valAxisTitle: this.chartConfig.axis.primary.name,
              valAxisTitleColor: this.chartConfig.series.primary.itemStyle.color.replace('#', ''),
              valAxisLabelColor: this.chartConfig.series.primary.itemStyle.color.replace('#', ''),
            },
            {
              showValAxisTitle: chart.values[1].showValAxisTitle,
              valAxisTitle: this.chartConfig.axis.secondary.name,
              valAxisTitleColor: this.chartConfig.series.secondary.itemStyle.color.replace('#', ''),
              valAxisLabelColor: this.chartConfig.series.secondary.itemStyle.color.replace('#', ''),
            },
          ],
        };
        if (chart.valAxisMajorUnit) {
          // 数值轴刻度步长
          comboProps.valAxisMajorUnit = chart.valAxisMajorUnit;
        }
        // 组合图表类型配置
        const comboTypes = [
          {
            type: this.seriesTypes.primary === 'bar' ? pptx.charts.BAR : pptx.charts.LINE,
            data: [chartData[0]],
            options: {
              dataLabelFormatCode: chart.dataLabelFormatCode[0],
              chartColors:
                this.seriesTypes.primary === 'bar'
                  ? this.primaryData.values.map(value => (value >= 0 ? this.chartConfig.series.primary.itemStyle.color.replace('#', '') : 'ee6666'))
                  : [this.chartConfig.series.primary.itemStyle.color.replace('#', '')],
              ...(this.seriesTypes.primary === 'bar'
                ? {
                    barDir: 'col',
                    barGrouping: 'clustered',
                  }
                : {
                    lineSize: 1,
                    lineDataSymbol: 'circle',
                    lineDataSymbolSize: 4,
                    lineSmooth: true,
                  }),
            },
          },
          {
            type: this.seriesTypes.secondary === 'bar' ? pptx.charts.BAR : pptx.charts.LINE,
            data: [chartData[1]],
            options: {
              dataLabelFormatCode: chart.dataLabelFormatCode[1],
              chartColors:
                this.seriesTypes.secondary === 'bar'
                  ? this.secondaryData.values.map(value => (value >= 0 ? this.chartConfig.series.secondary.itemStyle.color.replace('#', '') : 'ee6666'))
                  : [this.chartConfig.series.secondary.itemStyle.color.replace('#', '')],
              ...(this.seriesTypes.secondary === 'bar'
                ? {
                    barDir: 'col',
                    barGrouping: 'clustered',
                  }
                : {
                    lineSize: 1,
                    lineDataSymbol: 'circle',
                    lineDataSymbolSize: 4,
                    lineSmooth: true,
                  }),
              secondaryValAxis: true,
              secondaryCatAxis: true,
            },
          },
        ];

        // 添加组合图表
        slide.addChart(comboTypes, comboProps);
      }
    },
  },
  computed: {
    // 图表样式
    getChartStyle() {
      return {
        height: this.chartConfig.height + 'px',
      };
    },
  },
  watch: {
    /**
     * 监听数据变化
     * @description 当数据变化时自动更新图表
     */
    primaryData: {
      handler() {
        this.updateChart();
      },
      deep: true,
    },
    secondaryData: {
      handler() {
        this.updateChart();
      },
      deep: true,
    },
    chartConfig: {
      handler() {
        this.updateChart();
      },
      deep: true,
    },
    seriesTypes: {
      handler() {
        this.updateChart();
      },
      deep: true,
    },
    shareYAxis: {
      handler() {
        this.updateChart();
      },
      deep: true,
    },
  },

  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
  },

  beforeDestroy() {
    this.chart && this.chart.dispose();
    this.chart = null;
  },
};
</script>

<style lang="less" scoped>
.chart-wrapper {
  text-align: center;
  font-size: 18px;
  font-weight: bold;
  .chart {
    width: 100%;
  }
}
</style>
